package com.housekeeping.controller.api;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.housekeeping.model.Review;
import com.housekeeping.model.User;
import com.housekeeping.service.ReviewService;
import com.housekeeping.service.impl.ReviewServiceImpl;
import com.housekeeping.utils.ApiResponse;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
 * 评价控制器
 */
@WebServlet("/api/reviews/*")
public class ReviewApiController extends HttpServlet {
    private ReviewService reviewService = new ReviewServiceImpl();
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String pathInfo = req.getPathInfo();
        try {
            if (pathInfo == null || pathInfo.equals("/")) {
                handleGetAllReviews(req, resp);
            } else if (pathInfo.equals("/stats")) {
                handleGetReviewStats(req, resp);
            } else if (pathInfo.matches("/\\d+")) {
                handleGetReviewById(req, resp);
            } else if (pathInfo.matches("/order/\\d+")) {
                handleGetReviewByOrder(req, resp);
            } else if (pathInfo.matches("/service/\\d+")) {
                handleGetReviewsByService(req, resp);
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Not Found"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        try {
            handleCreateReview(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String pathInfo = req.getPathInfo();
        try {
            if (pathInfo != null && pathInfo.matches("/\\d+")) {
                handleDeleteReview(req, resp);
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Not Found"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }

    private void handleGetAllReviews(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        String ratingParam = req.getParameter("rating");
        List<Review> reviews;
        
        if (ratingParam != null && !ratingParam.trim().isEmpty()) {
            try {
                Integer rating = Integer.parseInt(ratingParam);
                reviews = reviewService.getReviewsByRating(rating);
            } catch (NumberFormatException e) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid rating parameter"));
                return;
            }
        } else {
            reviews = reviewService.getAllReviews();
        }
        
        ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(reviews));
    }

    private void handleGetReviewById(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        String pathInfo = req.getPathInfo();
        int reviewId = Integer.parseInt(pathInfo.substring(1));
        Review review = reviewService.getReviewById(reviewId);
        if (review != null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(review));
        } else {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Review not found"));
        }
    }

    private void handleGetReviewByOrder(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        String pathInfo = req.getPathInfo();
        int orderId = Integer.parseInt(pathInfo.substring(pathInfo.lastIndexOf("/") + 1));
        Review review = reviewService.getReviewByOrderId(orderId);
        if (review != null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(review));
        } else {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "No review for this order"));
        }
    }

    private void handleGetReviewsByService(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        String pathInfo = req.getPathInfo();
        int serviceId = Integer.parseInt(pathInfo.substring(pathInfo.lastIndexOf("/") + 1));
        
        String ratingParam = req.getParameter("rating");
        List<Review> reviews = reviewService.getReviewsByServiceId(serviceId);
        
        // 如果有rating参数，进一步筛选
        if (ratingParam != null && !ratingParam.trim().isEmpty()) {
            try {
                Integer rating = Integer.parseInt(ratingParam);
                reviews = reviews.stream()
                    .filter(review -> review.getRating().equals(rating))
                    .collect(java.util.stream.Collectors.toList());
            } catch (NumberFormatException e) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid rating parameter"));
                return;
            }
        }
        
        ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(reviews));
    }

    private void handleGetReviewStats(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        List<Review> allReviews = reviewService.getAllReviews();
        
        Map<String, Object> stats = new java.util.HashMap<>();
        stats.put("totalReviews", allReviews.size());
        
        // 计算平均评分
        double averageRating = allReviews.stream()
            .mapToInt(Review::getRating)
            .average()
            .orElse(0.0);
        stats.put("averageRating", Math.round(averageRating * 10.0) / 10.0);
        
        // 按评分分组统计
        Map<Integer, Long> ratingCounts = allReviews.stream()
            .collect(java.util.stream.Collectors.groupingBy(
                Review::getRating, 
                java.util.stream.Collectors.counting()
            ));
        
        stats.put("fiveStars", ratingCounts.getOrDefault(5, 0L));
        stats.put("fourStars", ratingCounts.getOrDefault(4, 0L));
        stats.put("threeStars", ratingCounts.getOrDefault(3, 0L));
        stats.put("twoStars", ratingCounts.getOrDefault(2, 0L));
        stats.put("oneStar", ratingCounts.getOrDefault(1, 0L));
        
        ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(stats));
    }

    private void handleCreateReview(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        HttpSession session = req.getSession(false);
        if (session == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        User currentUser = (User) session.getAttribute("user");
        if (currentUser == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        try {
            String requestBody = req.getReader().lines()
                .reduce("", (accumulator, actual) -> accumulator + actual);
            Map<String, Object> reviewData = objectMapper.readValue(
                requestBody, new TypeReference<Map<String, Object>>() {});
            Integer orderId = (Integer) reviewData.get("orderId");
            Integer serviceId = (Integer) reviewData.get("serviceId");
            Integer rating = (Integer) reviewData.get("rating");
            String content = (String) reviewData.get("content");
            
            // 使用 submitReview 方法，它包含了完整的业务逻辑校验
            if (reviewService.submitReview(orderId, currentUser.getUserId(), rating, content)) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("Review submitted successfully"));
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to submit review - check order status or if already reviewed"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid request data"));
        }
    }

    private void handleDeleteReview(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        String pathInfo = req.getPathInfo();
        int reviewId = Integer.parseInt(pathInfo.substring(1));
        
        HttpSession session = req.getSession(false);
        if (session == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        User currentUser = (User) session.getAttribute("user");
        if (currentUser == null || currentUser.getUserType() != 1) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(403, "Permission denied"));
            return;
        }
        
        Review review = reviewService.getReviewById(reviewId);
        if (review == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Review not found"));
            return;
        }
        
        if (reviewService.deleteReview(reviewId)) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("Review deleted successfully"));
        } else {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to delete review"));
        }
    }
} 